using System;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using EstimateTracker.Events;
using EstimateTracker.Services;
using JetBrains.Annotations;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;

namespace EstimateTracker.ViewModels
{
    public class TimerTabViewModel : ViewModelBase
    {
        private readonly ActivityViewModel _activityViewModel;
        private readonly TaskViewModel _taskViewModel;
        private readonly ProjectViewModel _projectViewModel;
        private readonly IEventAggregator _eventAggregator;
        private readonly ITimerService _service;
        private string _projectName;
        private string _activityName;
        private string _taskName;
        private double _taskEstimate;
        private double _taskHours;

        private readonly Timer _t;
        private IToggleTimer _timer;
        private string _timerLabel;
        private TimeSpan _time;
        private double _hoursSoFar;

        public TimerTabViewModel([NotNull] ActivityViewModel activityViewModel,[NotNull] TaskViewModel taskViewModel, ProjectViewModel projectViewModel, [NotNull] IEventAggregator eventAggregator, [NotNull] ITimerService service)
        {
            if (projectViewModel == null) throw new ArgumentNullException("projectViewModel");
            if (eventAggregator == null) throw new ArgumentNullException("eventAggregator");
            if (service == null) throw new ArgumentNullException("service");
            if (activityViewModel == null) throw new ArgumentNullException("activityViewModel");
            if (taskViewModel == null) throw new ArgumentNullException("taskViewModel");

            _projectViewModel = projectViewModel;
            _eventAggregator = eventAggregator;
            _service = service;
            _activityViewModel = activityViewModel;
            _taskViewModel = taskViewModel;

            _t = new Timer(1000) { AutoReset = true };
            _timer = new StartToggleTimer(_t, d => Time = new TimeSpan(0,(int)d ,0), NotifyTimerStoped);
            TimerLabel = "Start";
        }

        private void NotifyTimerStoped(double d)
        {
            _hoursSoFar += _service.SaveHours(TaskViewModel.SelectedTask, d);
        }

        public ProjectViewModel ProjectViewModel
        {
            get { return _projectViewModel; }
        }

        public ActivityViewModel ActivityViewModel
        {
            get
            {
                _activityViewModel.Initialize();
                return _activityViewModel;
            }
        }

        public TaskViewModel TaskViewModel
        {
            get
            {
                _eventAggregator.GetEvent<UpdateTaskActualsEvent>().Subscribe(UpdateHours);
                _taskViewModel.Initialize();
                return _taskViewModel;
            }
        }

        private void UpdateHours(double h)
        {
            _hoursSoFar = h;
            TaskHours = h; //TaskHours < 0.1 || _hoursSoFar < 0.1 ? _hoursSoFar : TaskHours;
        }

        public ICommand AddProject
        {
            get
            {
                return new DelegateCommand(() => ProjectViewModel.AddProject(ProjectName));
            }
        }

        public ICommand AddActivity
        {
            get
            {
                return new DelegateCommand(() => ActivityViewModel.AddActivity(ActivityName, ProjectViewModel.SelectedProject));
            }
        }

        public ICommand AddTask
        {
            get
            {
                return new DelegateCommand
                (
                    () =>
                    {
                        if (ActivityViewModel.SelectedActivity == null)
                        {
                            MessageBox.Show("Please select an activity");
                            return;
                        }
                        TaskViewModel.AddTask(TaskName, TaskEstimate, ActivityViewModel.SelectedActivity);
                    }
                );
            }
        }

        public string ActivityName
        {
            get { return _activityName; }
            set
            {
                _activityName = value;
                OnPropertyChanged("ActivityName");
            }
        }
        
        public string ProjectName
        {
            get { return _projectName; }
            set
            {
                _projectName = value;
                OnPropertyChanged("ProjectName");
            }
        }

        public string TaskName
        {
            get { return _taskName; }
            set
            {
                _taskName = value;
                OnPropertyChanged("TaskName");
            }
        }

        public double TaskEstimate
        {
            get { return _taskEstimate; }
            set
            {
                _taskEstimate = value;
                OnPropertyChanged("TaskEstimate");
            }
        }
        
        public double TaskHours
        {
            get { return _taskHours; }
            set
            {
                _taskHours = value;
                OnPropertyChanged("TaskHours");
            }
        }
        
        public ICommand NotifyTimer
        {
            get
            {
                return new DelegateCommand
                (
                    () =>
                    {
                        TimerLabel = _timer.Label;
                        _timer = _timer.Toggle();
                    }
                );
            }
        }

        public string TimerLabel
        {
            get { return _timerLabel; }
            set
            {
                _timerLabel = value;
                OnPropertyChanged("TimerLabel");
            }
        }

        public TimeSpan Time
        {
            get { return _time; }
            set
            {
                _time = value;
                TaskHours = _service.UpdateTime(_hoursSoFar, _time);
                OnPropertyChanged("Time");
            }
        }
    }
}